Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New Syntax for Capture Variables and Explicit Capture Polymorphism v2 #22902

Open
wants to merge 16 commits into
base: main
Choose a base branch
from

Conversation

bracevac
Copy link
Contributor

@bracevac bracevac commented Apr 1, 2025

Closes #22490
Builds on #22725
Supersedes #22758

This aim of this PR is reducing the clunkyness of the explicit capture polymorphism syntax following internal discussions.

  • Nice to have: partial applications and compatibility with named type arguments
import language.experimental.namedTypeArguments
foo[{a,b}]
foo[cap D = {x}]
  • Rebase on Separation checking for product types #22539 and patch all tests.
  • Document the parser changes for capture checking in the internal syntax.md.
  • Add specialized syntax error messages for cap lists & co. (make separate issue)
  • Remove the old [C^] syntax for good.
  • Make cap members and lists pretty-printed (with option to turn off). (separate issue, let's wait for under-the-hood changes to the capset representation)
  • Let parser mark capture variables with some attachment to be used by later phases.
  • Update CC language reference with the new syntax.

Neg test use-capset revealed that type param
clauses are incorrectly parsed when a capset
parameter has an annotation.
@bracevac bracevac requested a review from noti0na1 April 1, 2025 17:35
@bracevac bracevac marked this pull request as ready for review April 2, 2025 13:46
@bracevac bracevac requested a review from odersky April 2, 2025 13:46
@odersky
Copy link
Contributor

odersky commented Apr 2, 2025

I think it would be good to open a thread on contributors to discuss the new syntax. That way, p[eople can weigh in with opinions and proposals.

Copy link
Member

@noti0na1 noti0na1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall LGTM

@odersky
Copy link
Contributor

odersky commented Apr 6, 2025

Looking at the test cases I am now less sure this is the best syntax. In particular I find the cap modifier a bit jarring, and it's also not immediately obvious to me where and why we need {...} around arguments.

We should try to get some representative test cases, evaluate how common we believe they will be, and compare different syntaxes with each other. That's what we did for the givens before we settled on one syntax. We could have that discussion thread here on the PR or on contributors.

@bracevac
Copy link
Contributor Author

bracevac commented Apr 6, 2025

Looking at the test cases I am now less sure this is the best syntax. In particular I find the cap modifier a bit jarring, and it's also not immediately obvious to me where and why we need {...} around arguments.

We discussed this. They are needed around all capture arguments and bounds of capture variables. The previous design allowed dropping them for singleton sets, but we didn't want it. It's regular, though I have to say, while patching the examples, I tended to subconsciously go back to braceless singletons from time to time only to be surprised by syntax errors...

What should be the alternative for cap as a modifier? We somehow have to mark those type variables which are capture variables. Does that mean we are going back to [C^]? I find it too cryptic compared to [cap C]. Though I find member declarations cap type C somewhat wordy compared to just cap C or type C^.

We should try to get some representative test cases, evaluate how common we believe they will be, and compare different syntaxes with each other. That's what we did for the givens before we settled on one syntax. We could have that discussion thread here on the PR or on contributors.

🫡 on it!

bracevac added 2 commits April 9, 2025 01:31
Plus added a test demonstrating branding
and uses of upper and lower bounds.
Capture set variables `X^` are represented as regular type variables with a
special upper bound `CapSet`. For instance, `Source` could be equivalently
Capture-set variables `cap X` are represented as regular type variables within the special interval
`>: CapSet <: CapSet^`. For instance, `Source` could be equivalently
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would say the interval of a capture variable is: >: {} <: {cap}, to hide the internal CapSet.

In a separate paragraph, we can point out CapSet is a special internal type to carry capture sets, and cap X is de-sugared to X >: CapSet <: CapSet^

```scala
def main() =
// We can close over anything branded by the 'trusted' capability, but nothing else
def runSecure[cap C >: {trusted} <: {trusted}](block: () ->{C} Unit): Unit = ...
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think a fixed bound is a good example to illustrate the polymorphism...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

CC: Better End-User Syntax for Declaring and Mentioning Capture Variables
3 participants